package charRecognition;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.Hashtable;

import preproc.Image;

import segmentation.CharInfo;
import utils.Constants;
import utils.Utils;
import weka.attributeSelection.SVMAttributeEval;
import weka.classifiers.Classifier;
import weka.classifiers.functions.LibSVM;
import weka.classifiers.functions.MultilayerPerceptron;
import weka.classifiers.functions.SMO;
import weka.core.Instance;
import weka.core.Instances;
import wlsvm.WLSVM;

public class Recognizer {
	Classifier classifier = new MultilayerPerceptron();
	Hashtable<String, WLSVM> svmTable = new Hashtable<String, WLSVM>();
	public Recognizer()
	{
		((MultilayerPerceptron) classifier).setHiddenLayers("75");
		
	}
	
	public String recognizeSVM(Image img)
	{
		String s = "";
		for (CharInfo c: img.chars) {
			s = s + recognizeSVM(c);
		}
		return s;
	}
	public String recognizeSVM(CharInfo c)
	{
		Instance prevInst = null;
			Instance inst = null;
			try {
				
				inst = WekaUtils.getInstance(c.extractFeatures());
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				System.exit(0);
			}
			
			
			try {
				for(Character character : WekaUtils.classes)
				{
					
					if(svmTable.containsKey(character.toString()))
					{	
					double [] val =  svmTable.get(character.toString()).distributionForInstance(inst);
					System.out.println("Clasificatorul a zis "+val[0]+" "+val[1]+" pentru "+character.toString());
					if (prevInst==null) prevInst = inst;
					double [] val2 = svmTable.get(character.toString()).distributionForInstance(prevInst);
					prevInst = inst;
					}
				//if(val == 1){return character.toString();}
				}
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				System.exit(0);
			}
			return "";
	}
	
	public String recognize(Image img) {
		String s = "";
		for (CharInfo c: img.chars) {
			s = s + recognize(c);
		}
		return s;
	}
	
	Instance prevInst = null;
	public String recognize(CharInfo c) {
		Instance inst = null;
		try {
			
			inst = WekaUtils.getInstance(c.extractFeatures());
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.exit(0);
		}
		
		double val = -1;
		try {
			val = classifier.classifyInstance(inst);
			if (prevInst==null) prevInst = inst;
			double val2 = classifier.classifyInstance(prevInst);
			prevInst = inst;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.exit(0);
		}
		return WekaUtils.getClass(val)+"";
	}

	public void trainSVMClassifier(String s, String path)
	{
		Instances data = null;
		try {
			data = WekaUtils.fetchData("SVMTrain\\"+path+".arff");
			data.setClassIndex(CharInfo.getNumFeatures());
		} catch (IOException e) {
			e.printStackTrace();
			System.exit(0);
		}
		
		try {
			WLSVM c = new WLSVM();
			c.setSVMType(0);
			c.setProbability(1);
			c.setKernelType(1);
			c.buildClassifier(data);
			saveSVMModel(c,path);
			svmTable.put(s, c);
		} catch (Exception e) {
			System.err.println("Could not train classifier");
			e.printStackTrace();
			System.exit(0);
		}
	}
	
	public void trainClassifier() {
		
		Instances data = null;
		try {
			data = WekaUtils.fetchData(Constants.TRAIN_ARFF);
			data.setClassIndex(CharInfo.getNumFeatures());
		} catch (IOException e) {
			e.printStackTrace();
			System.exit(0);
		}
		
		try {
			classifier.buildClassifier(data);
		} catch (Exception e) {
			System.err.println("Could not train classifier");
			e.printStackTrace();
			System.exit(0);
		}
	}

	public void saveSVMModel(Classifier c,String s) {
		try {
			WekaUtils.serializeModel(c, "SVMModels\\"+s+".model");
		} catch (Exception e) {
			System.err.println("Could not serialize model");
			e.printStackTrace();
		}	
	}
	
	// save the model to a file
	public void saveModel() {
		try {
			WekaUtils.serializeModel(classifier, Constants.MODEL_FILE);
		} catch (Exception e) {
			System.err.println("Could not serialize model");
			e.printStackTrace();
		}	
	}
	
	public void loadSVMModel()
	{
		
		WLSVM c = new WLSVM();
		c.setSVMType(0);
		c.setProbability(1);
		c.setKernelType(1);
		

		try {
			File dir = new File(Constants.SVM_MODEL_DIR);
			String[] children = dir.list(Utils.filter);
			for(int i=0;i<children.length;i++)
			{
				System.out.println("incarc "+children[i]);
				String key = children[i].split("_")[1].split("\\.")[0];
				c = (WLSVM)WekaUtils.deserializeModel(Constants.SVM_MODEL_DIR+children[i]);
				svmTable.put(key, c);
			}
		} catch (Exception e) {
			System.err.println("Could not deserialize model");
			e.printStackTrace();
		}	
	}
	
	// load the model from the file
	public void loadModel() {
		try {
			classifier = WekaUtils.deserializeModel(Constants.MODEL_FILE);
		} catch (Exception e) {
			System.err.println("Could not deserialize model");
			e.printStackTrace();
		}	
	}
}
